/**
 * Copyright (C) 2010-2016 eBusiness Information, Excilys Group
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed To in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.ohosannotations.internal.rclass;

import com.helger.jcodemodel.JDirectClass;
import com.helger.jcodemodel.JFieldRef;

import org.ohosannotations.OhosAnnotationsEnvironment;
import org.ohosannotations.helper.CaseHelper;
import org.ohosannotations.rclass.IRClass;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;

/**
 * RClass
 *
 * @since 2021-06-16
 */
public class Rclass implements IRClass {
    private static final String DOT = ".";
    private final Map<Integer, String> idQualifiedNamesByIdValues = new HashMap<>();
    private final Set<String> idQualifiedNames = new HashSet<>();

    private final String mRqualifiedName;

    /**
     * RClass
     *
     * @param typeElement 类型元素
     */
    public Rclass(TypeElement typeElement) {
        if (typeElement != null) {
            mRqualifiedName = getString(typeElement);
        } else {
            mRqualifiedName = "";
        }
    }

    private String getString(TypeElement typeElement) {
        String lifiedName = typeElement.getQualifiedName().toString();
        List<? extends Element> idEnclosedElements = typeElement.getEnclosedElements();

        List<VariableElement> idFields = ElementFilter.fieldsIn(idEnclosedElements);

        for (VariableElement idField : idFields) {
            TypeKind fieldType = idField.asType().getKind();
            if (fieldType.isPrimitive() && fieldType.equals(TypeKind.INT)) {
                String idQualifiedName = lifiedName + DOT + idField.getSimpleName();
                idQualifiedNames.add(idQualifiedName);
                Integer idFieldId = (Integer) idField.getConstantValue();
                if (idFieldId != null) {
                    idQualifiedNamesByIdValues.put(idFieldId, idQualifiedName);
                }
            }
        }
        return lifiedName;
    }

    @Override
    public boolean containsIdValue(Integer idValue) {
        return idQualifiedNamesByIdValues.containsKey(idValue);
    }

    @Override
    public String getIdQualifiedNameById(Integer idValue) {
        return idQualifiedNamesByIdValues.get(idValue);
    }

    @Override
    public boolean containsField(String name) {
        boolean isContainsField = idQualifiedNames.contains(mRqualifiedName + DOT + name);
        if (!isContainsField) {
            String snakeCaseName = CaseHelper.camelCaseToSnakeCase(name);
            isContainsField = idQualifiedNames.contains(mRqualifiedName + DOT + snakeCaseName);
        }
        return isContainsField;
    }

    @Override
    public String getIdQualifiedNameByName(String name) {
        String idQualifiedName = mRqualifiedName + DOT + name;

        if (idQualifiedNames.contains(idQualifiedName)) {
            return idQualifiedName;
        } else {
            String snakeCaseName = CaseHelper.camelCaseToSnakeCase(name);
            idQualifiedName = mRqualifiedName + DOT + snakeCaseName;
            if (idQualifiedNames.contains(idQualifiedName)) {
                return idQualifiedName;
            } else {
                return null; // 返回空
            }
        }
    }

    @Override
    public JFieldRef getIdStaticRef(Integer idValue, OhosAnnotationsEnvironment environment) {
        String layoutFieldQualifiedName = getIdQualifiedNameById(idValue);
        return extractIdStaticRef(environment, layoutFieldQualifiedName);
    }

    @Override
    public JFieldRef getIdStaticRef(String name, OhosAnnotationsEnvironment environment) {
        String layoutFieldQualifiedName = getIdQualifiedNameByName(name);
        return extractIdStaticRef(environment, layoutFieldQualifiedName);
    }

    /**
     * extractIdStaticRef
     *
     * @param environment environment
     * @param layoutFieldQualifiedName layoutFieldQualifiedName
     * @return JFieldRef
     */
    public static JFieldRef extractIdStaticRef(OhosAnnotationsEnvironment environment,
        String layoutFieldQualifiedName) {
        if (layoutFieldQualifiedName != null) {
            int fieldSuffix = layoutFieldQualifiedName.lastIndexOf('.');
            String fieldName = layoutFieldQualifiedName.substring(fieldSuffix + 1);
            String substring = layoutFieldQualifiedName.substring(0, fieldSuffix);
            JDirectClass directClass = (JDirectClass) environment.getJClass(substring);
            return directClass.staticRef(fieldName);
        } else {
            return null; // 返回空
        }
    }
}
